package com.zhangfb95.crosschain.console.util;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;

import java.util.LinkedList;
import java.util.Stack;

public class TokenUtil {

    public static String[] tokenizeCommand(String line) {
        BiMap<Character, Character> tokens = HashBiMap.create();

        tokens.put('"', '"');
        tokens.put('\'', '\'');
        tokens.put('{', '}');
        tokens.put('[', ']');
        tokens.put('(', ')');

        String trimLine = line.trim();

        LinkedList<StringBuilder> items = new LinkedList<StringBuilder>();
        items.add(new StringBuilder());

        boolean isEscape = false;
        Stack<Character> tokenStack = new Stack<>();

        for (int i = 0; i < trimLine.length(); ++i) {
            Character c = trimLine.charAt(i);

            if (!isEscape) {
                if (c == '\\') {
                    isEscape = true;
                    continue;
                }

                if ((c == ' ' || c == '\t') && tokenStack.isEmpty()) {
                    if (!items.getLast().isEmpty()) {
                        items.add(new StringBuilder());
                    }

                    continue;
                }

                Character token = tokens.get(c);
                if (token == null) {
                    token = tokens.inverse().get(c);
                }

                if (token != null) {
                    if (!tokenStack.isEmpty() && tokenStack.peek().equals(token)) {
                        tokenStack.pop();
                    } else {
                        tokenStack.add(c);
                    }
                }
            }

            items.getLast().append(c);
        }

        return items.stream().map(StringBuilder::toString).toList().toArray(new String[]{});
    }
}
